<html>
 <head>
  <meta charset="UTF-8">
 </head>
 <body>
  <h1 data-lake-id="TOMw1" id="TOMw1"><span data-lake-id="u59096fb1" id="u59096fb1">典型回答</span></h1>
  <p data-lake-id="ubf127a93" id="ubf127a93"><br></p>
  <p data-lake-id="u9f274a96" id="u9f274a96"><span data-lake-id="u9699272d" id="u9699272d">限流是一种控制流量的技术，用于保护系统免受突发流量或恶意流量的影响。其基本原理是通过控制请求的速率或数量，确保系统在可承受的范围内运行。</span></p>
  <p data-lake-id="uaa82f26f" id="uaa82f26f"><br></p>
  <p data-lake-id="u65231743" id="u65231743"><span data-lake-id="u89a6b56b" id="u89a6b56b">常见的限流算法有：</span></p>
  <ol list="uf8012396">
   <li fid="u926513e0" data-lake-id="uafb330c2" id="uafb330c2"><strong><span data-lake-id="ub59869c6" id="ub59869c6">漏桶算法</span></strong><span data-lake-id="u2514f795" id="u2514f795">：系统请求先进入漏桶，再从漏桶中逐一取出请求执行，控制漏桶的流量。</span></li>
   <li fid="u926513e0" data-lake-id="ub9fe98e1" id="ub9fe98e1"><strong><span data-lake-id="uffd1e5bf" id="uffd1e5bf">令牌桶算法</span></strong><span data-lake-id="u1738f468" id="u1738f468">：系统请求会得到一个令牌，从令牌桶中取出一个令牌执行，控制令牌桶中令牌的数量。</span></li>
   <li fid="u926513e0" data-lake-id="u273235e8" id="u273235e8"><strong><span data-lake-id="u59230191" id="u59230191">计数器算法</span></strong><span data-lake-id="ud79616a1" id="ud79616a1">：系统请求被计数，通过比较当前请求数与限流阈值来判断是否限流。</span></li>
   <li fid="u926513e0" data-lake-id="uc8db0152" id="uc8db0152"><strong><span data-lake-id="u7ad63ec4" id="u7ad63ec4">可以阻塞算法</span></strong><span data-lake-id="u7352398a" id="u7352398a">：当系统达到限流阈值时，不再接受新请求，等到限流阈值降下来再接受请求。</span></li>
   <li fid="u926513e0" data-lake-id="u9b182d09" id="u9b182d09"><strong><span data-lake-id="u2d7a7a2f" id="u2d7a7a2f">令牌环算法</span></strong><span data-lake-id="ufdf7cbb9" id="ufdf7cbb9">：与令牌桶算法类似，但是在多个令牌桶之间形成环形结构，以便在不同的请求处理速率之间进行平衡。</span></li>
   <li fid="u926513e0" data-lake-id="u59af1c3f" id="u59af1c3f"><strong><span data-lake-id="uc9499e6a" id="uc9499e6a">最小延迟算法</span></strong><span data-lake-id="u5af209c5" id="u5af209c5">：基于预测每个请求的处理时间，并在处理完请求后进行延迟，以控制请求的速率。</span></li>
   <li fid="u926513e0" data-lake-id="u98ad7789" id="u98ad7789"><strong><span data-lake-id="u09ad57f1" id="u09ad57f1">滑动窗口</span></strong><span data-lake-id="uaf2ab7ac" id="uaf2ab7ac">：基于一个固定大小的时间窗口，允许在该时间窗口内的请求数不超过设定的阈值。这个时间窗口随着时间的推移不断滑动，以适应不同时间段内的请求流量。</span></li>
  </ol>
  <p data-lake-id="uac422080" id="uac422080"><span data-lake-id="u2a63766c" id="u2a63766c">​</span><br></p>
  <p data-lake-id="u13859ac9" id="u13859ac9"><strong><span data-lake-id="u8b09c6fa" id="u8b09c6fa">其中比较常见的就是漏桶和令牌桶，他们之间最大的区别就是应对突发流量的能力。</span></strong></p>
  <p data-lake-id="u65cbe748" id="u65cbe748"><span data-lake-id="u89899870" id="u89899870">​</span><br></p>
  <h1 data-lake-id="A4g3s" id="A4g3s"><span data-lake-id="u0145e52a" id="u0145e52a">扩展知识</span></h1>
  <p data-lake-id="ub9f20b92" id="ub9f20b92"><br></p>
  <h2 data-lake-id="u0s4Y" id="u0s4Y"><span data-lake-id="u1f8a539e" id="u1f8a539e">漏桶算法</span></h2>
  <p data-lake-id="ube2d2f88" id="ube2d2f88"><span data-lake-id="u13ba3932" id="u13ba3932">漏桶算法是一种流量控制算法，可以平滑控制流量的进出，原理比较简单：假设我们有一个水桶按固定的速率向下方滴落一滴水，无论有多少请求，请求的速率有多大，都按照固定的速率流出，对应到系统中就是按照固定的速率处理请求。</span></p>
  <p data-lake-id="uafb9afd2" id="uafb9afd2"><span data-lake-id="udacf4b4b" id="udacf4b4b">​</span><br></p>
  <p data-lake-id="u31467a38" id="u31467a38"><img src="https://cdn.nlark.com/yuque/0/2023/jpeg/5378072/1677905160737-5d9fc531-399d-470a-ab28-325a5ab183fb.jpeg?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_41%2Ctext_SmF2YSA4IEd1IFA%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10"></p>
  <p data-lake-id="uf3638c80" id="uf3638c80"><br></p>
  <p data-lake-id="uee46f20a" id="uee46f20a"><br></p>
  <p data-lake-id="u408e92df" id="u408e92df"><span data-lake-id="u125dd9db" id="u125dd9db">漏桶算法通过一个固定容量的漏桶来控制请求的处理速率，每个请求被看作是一定数量的水，需要先放到漏桶中。当漏桶满时，请求将被拒绝或延迟处理，从而保证了系统的稳定性。</span></p>
  <p data-lake-id="u88b7ab48" id="u88b7ab48"><span data-lake-id="ua12eac1c" id="ua12eac1c">​</span><br></p>
  <p data-lake-id="u9fed89b4" id="u9fed89b4"><span data-lake-id="u1076b095" id="u1076b095">漏桶通过定时器的方式将水以恒定的速率流出，与请求的数量无关，从而平滑控制了请求的处理速率。当请求到来时，先将请求看作是一定数量的水，需要将这些水放入漏桶中。</span></p>
  <p data-lake-id="ue6113f66" id="ue6113f66"><span data-lake-id="ucfa69d14" id="ucfa69d14">​</span><br></p>
  <p data-lake-id="u8506a34c" id="u8506a34c"><span data-lake-id="u956b6ae3" id="u956b6ae3">如果漏桶未满，请求将被立即处理并从漏桶中取出对应数量的水。如果漏桶已满，请求将被拒绝或被延迟处理，直到漏桶中有足够的空间存放请求对应数量的水。</span></p>
  <p data-lake-id="u54033e9f" id="u54033e9f"><span data-lake-id="ucb508628" id="ucb508628">​</span><br></p>
  <p data-lake-id="ua21c9d91" id="ua21c9d91"><span data-lake-id="uae74e41d" id="uae74e41d">当定时器触发时，漏桶中的水以恒定的速率流出，此时可以继续处理请求。</span></p>
  <p data-lake-id="ud1ae8559" id="ud1ae8559"><span data-lake-id="uba2e2819" id="uba2e2819">​</span><br></p>
  <p data-lake-id="u4abdc32f" id="u4abdc32f"><span data-lake-id="u38ce3929" id="u38ce3929">总之，</span><strong><span data-lake-id="uc5dfe4e1" id="uc5dfe4e1">漏桶算法通过一个固定容量的漏桶来控制请求的处理速率，可以平滑控制流量的进出，保证系统的稳定性和安全性。</span></strong></p>
  <p data-lake-id="uc55c8528" id="uc55c8528"><span data-lake-id="u41bdf4f0" id="u41bdf4f0">​</span><br></p>
  <p data-lake-id="ub4c3444f" id="ub4c3444f"><span data-lake-id="u16d559b1" id="u16d559b1">但需要注意的是，</span><strong><span data-lake-id="uf2959649" id="uf2959649">漏桶算法无法处理突发流量</span></strong><span data-lake-id="u4bf07988" id="u4bf07988">，因为他只能按照固定的速度来处理请求，如果某个请求的流量突增，因为漏桶的机制就导致了他还是只能一个一个的按照固定速度进行消费。</span></p>
  <p data-lake-id="u80deedd3" id="u80deedd3"><span data-lake-id="u1699130e" id="u1699130e">​</span><br></p>
  <p data-lake-id="ub1c29662" id="ub1c29662"><span data-lake-id="u21450fc5" id="u21450fc5">为了解决这种突发流量的问题，就有了</span><strong><span data-lake-id="u0327a822" id="u0327a822">令牌桶算法</span></strong><span data-lake-id="u3ee7fa83" id="u3ee7fa83">。</span></p>
  <h2 data-lake-id="tStwD" id="tStwD"><span data-lake-id="u20e08bc4" id="u20e08bc4">令牌桶算法</span></h2>
  <p data-lake-id="ub03b146f" id="ub03b146f"><br></p>
  <p data-lake-id="ufe874712" id="ufe874712"><span data-lake-id="u263c866f" id="u263c866f">令牌桶其实和漏桶的原理类似，</span><strong><span data-lake-id="u6e414e26" id="u6e414e26">令牌桶按固定的速率往桶里放入令牌，并且只要能从桶里取出令牌就能通过。</span></strong></p>
  <p data-lake-id="uf9680415" id="uf9680415"><span data-lake-id="uc9b789ad" id="uc9b789ad">​</span><br></p>
  <p data-lake-id="ubace4142" id="ubace4142"><span data-lake-id="uff74b227" id="uff74b227">也就是说，我不管现在请求量是多还是少，都有一个线程以固定的速率再往桶里放入令牌，而有请求过来的时候，就会去桶里取出令牌，能取到就执行，取不到就拒绝或者阻塞。</span></p>
  <p data-lake-id="u403ed7c7" id="u403ed7c7"><span data-lake-id="u676c4419" id="u676c4419">​</span><br></p>
  <p data-lake-id="u365305e8" id="u365305e8"><span data-lake-id="u902c39e7" id="u902c39e7">​</span><br></p>
  <p data-lake-id="u13bea553" id="u13bea553"><img src="https://cdn.nlark.com/yuque/0/2023/jpeg/5378072/1677905589842-94862a34-ff49-43b5-b61e-e134d4980f76.jpeg?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_41%2Ctext_SmF2YSA4IEd1IFA%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10"></p>
  <p data-lake-id="u57ee8c9d" id="u57ee8c9d"><br></p>
  <p data-lake-id="ufac5b16a" id="ufac5b16a"><span data-lake-id="u07048e11" id="u07048e11">​</span><br></p>
  <p data-lake-id="u6c6edc30" id="u6c6edc30"><span data-lake-id="u8b22fd48" id="u8b22fd48">令牌桶通过定时器的方式向桶中添加令牌，每秒钟添加一定数量的令牌，从而平滑控制了请求的处理速率。这样如果突发流量过来了，只要令牌桶中还有足够的令牌，就可以快速的执行，而不是像漏桶一样还要按照固定速率执行。</span></p>
  <p data-lake-id="u16e9a8d5" id="u16e9a8d5"><span data-lake-id="ud23798b7" id="ud23798b7">​</span><br></p>
  <p data-lake-id="u9560f716" id="u9560f716"><span data-lake-id="ufb8d6e50" id="ufb8d6e50">令牌桶的好处就是把流量给平滑掉了，在流量不高的时候也会不断的向桶中增加令牌，这样就有足够的令牌可供请求消费。</span></p>
  <p data-lake-id="uf0bc2a87" id="uf0bc2a87"><br></p>
  <p data-lake-id="u063b4656" id="u063b4656"><strong><span data-lake-id="u8e81945a" id="u8e81945a">在Java中，我们可以借助Guava提供的RateLimiter来实现令牌桶。</span></strong></p>
  <p data-lake-id="ufaf01161" id="ufaf01161"><br></p>
  <p data-lake-id="uff58f767" id="uff58f767"><br></p>
  <h2 data-lake-id="q6tTI" id="q6tTI"><span data-lake-id="uc2660ecf" id="uc2660ecf">滑动窗口算法</span></h2>
  <p data-lake-id="u6ba5588a" id="u6ba5588a"><br></p>
 </body>
</html>